package com.bac.rentmap.ad.add;

/**
 * Used for add flat add from the site page to database.
 *
 * @author Sergey Zhmura
 */
import java.util.Date;
import java.util.Properties;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import com.bac.rentmap.ad.flat.FlatAd;
import com.bac.rentmap.ad.flat.FlatAdDao;
import org.springframework.beans.factory.annotation.Required;

import com.bac.rentmap.ad.flat.crawler.FlatCrawledAd;
import com.bac.rentmap.ad.flat.image.FlatImageService;
import com.bac.rentmap.ad.util.DateHelper;
import com.bac.rentmap.jdo.JdoSupport;

public class AddFlatService extends JdoSupport {
    private static final String SUPPORT_EMAIL = "support@hatu.by";
    private static final Logger log = Logger.getLogger(AddFlatService.class
            .getName());
    private FlatImageService flatImageService;
    private DateHelper dateHelper;

    private FlatAdDao flatAdDao;

    public void saveFlat(FlatCrawledAd flat, String baseUrl, String sessionId) {
        insertOrUpdateFlat(flat, baseUrl, sessionId);
    }

    private void insertOrUpdateFlat(FlatCrawledAd flat, String baseUrl, String sessionId) {
        PersistenceManager pm = getPersistenceManager();
        try {
            FlatAd flatAd = flatAdDao.find(flat.getStreet(),
                    flat.getBuilding(), flat.getPhone(),
                    pm);
            if(flatAd !=  null && flatAd.getEmail() != null && flat.getEmail() != null
                    && flat.getEmail().equals(flatAd.getEmail())) {
                updateFlatAd(flat, flatAd, baseUrl, sessionId, pm);
            }
            else{
                insertFlatCrawledAd(flat, baseUrl, sessionId, pm);
            }
        } finally {
            pm.close();
        }
    }
    private void updateFlatAd(FlatCrawledAd flatCrawledAd, FlatAd flatAd, String baseUrl, String sessionId, PersistenceManager pm){
        Date now = new Date();
        flatCrawledAd.setPublishingDate(now);
        pm.makePersistent(flatCrawledAd);

        flatAd.setLastPublishingDate(new Date());
        flatAd.setRatingCalculated(false);
        flatImageService.deleteAll(sessionId, pm);
        sendExistingFlatAdEmail(flatCrawledAd, flatAd, baseUrl);
    }
    private void insertFlatCrawledAd(FlatCrawledAd flat, String baseUrl, String sessionId, PersistenceManager pm){
        log.info("Adding add " + flat);
        flat.setPublishingDate(new Date());
        flat = pm.makePersistent(flat);
        log.fine("Persisted flat ad with id: " + flat.getId());
        flatImageService.attachToFlatCrawledAd(sessionId, flat);
        sendNewFlatCrawledAdEmail(flat, baseUrl);
    }
    private void sendExistingFlatAdEmail(FlatCrawledAd flatCrawledAd, FlatAd flatAd, String baseUrl) {
        String address = flatCrawledAd.getStreet() + ", " + flatCrawledAd.getBuilding();
        String msgBody = "Добрый день,\nВаше объявление о сдаче квартиры по адресу " + address +
                " не было добавлено. У вас уже есть объявление по этому адресу " + baseUrl
                + "/ad/manage/view.do?secureId=" + flatAd.getSecureId()
                + "\n. Если вы хотите отредактировать старое объявление воспользуйтейсь ссылкой выше.";
        sendEmail("хату.бы: Ошибка добавления объвления", msgBody, flatCrawledAd.getEmail());
    }
    private void sendNewFlatCrawledAdEmail(FlatCrawledAd flatCrawledAd, String baseUrl) {
        String address = flatCrawledAd.getStreet() + ", " + flatCrawledAd.getBuilding();
        String msgBody = "Добрый день,\nВаше объявление о сдаче квартиры по адресу " + address + 
            " успешно добавлено. Удалить или отредактировать объявление можно по ссылке " + baseUrl
                + "/ad/manage/view.do?secureId=" + flatCrawledAd.getSecureId() + "\n";
        
        msgBody += "\nКоличество комнат: " + flatCrawledAd.getRoom();
        msgBody += "\nТелефон: " + flatCrawledAd.getPhone();
        msgBody += "\nЭлектронная почта: " + nullSafeToString(flatCrawledAd.getEmail());
        msgBody += "\nЦена в месяц: " + flatCrawledAd.getPrice();
        msgBody += "\nДополнительная информация об объявлении: " + nullSafeToString(flatCrawledAd.getDescription());

        sendEmail("хату.бы: Объявление добавлено", msgBody, flatCrawledAd.getEmail());
    }

    private String nullSafeToString(Object object){
        if(object == null){
            return "";
        }
        return object.toString();
    }

    private void sendEmail(String subject, String body, String email){
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);
        try {
            MimeMessage msg = new MimeMessage(session);
            if(email != null){
                msg.addRecipient(Message.RecipientType.CC, new InternetAddress(
                        SUPPORT_EMAIL));
            }
            else{
                email = SUPPORT_EMAIL;
            }
            log.fine("Sending email to " + email);
            msg.addRecipient(Message.RecipientType.TO, new InternetAddress(
                    email));

            msg.setFrom(new InternetAddress("dev7000@gmail.com"));

            msg.setSubject(subject, "UTF-8");
            msg.setText(body, "UTF-8");
            Transport.send(msg);

        } catch (AddressException e) {
            log.warning("Can't send new ad email " + e);
        } catch (MessagingException e) {
            log.warning("Can't send new ad email " + e);
        }
    }

    @Required
    public void setFlatImageService(FlatImageService flatImageService) {
        this.flatImageService = flatImageService;
    }

    @Required
    public void setDateHelper(DateHelper dateHelper) {
        this.dateHelper = dateHelper;
    }

    @Required
    public void setFlatAdDao(FlatAdDao flatAdDao) {
        this.flatAdDao = flatAdDao;
    }
}
